﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using DimensionsHelper.Common.Contracts;
using DimensionsHelper.Common.Metadata.Script;

namespace DimensionsHelper.Common.Sql;

/// <summary>
///     SQL字段的数据类型，生成SQL脚本时，将依据不同的值类型生成不同的字符串。
/// </summary>
public enum MetadataSqlFieldValueType
{
    /// <summary>
    ///     文本类型，SQL脚本中，将使用双引号包裹。
    /// </summary>
    [Description(nameof(Text))]
    Text,

    /// <summary>
    ///     分类字段，SQL脚本中，将使用花括号包裹。
    /// </summary>
    [Description(nameof(Categorical))]
    Categorical,

    /// <summary>
    ///     整数字段，SQL脚本中，将使用原始文本，如果给定值不是数字，应当抛出错误。
    /// </summary>
    [Description(nameof(Long))]
    Long,

    /// <summary>
    ///     小数字段，SQL脚本中，将使用原始文本，如果给定值不是数字，应当抛出错误。
    /// </summary>
    [Description(nameof(Double))]
    Double
}

/// <summary>
///     需要在SQL脚本中额外添加的字段名和字段值。
/// </summary>
[Serializable]
public class MetadataSqlAppendField : INamedObject
{
    /// <summary>
    ///     添加字段的数据类型。
    /// </summary>
    public MetadataSqlFieldValueType Type { get; set; } = MetadataSqlFieldValueType.Categorical;

    /// <summary>
    ///     赋值配置集合，可以给不同的值配置不同的筛选条件和文件名。
    /// </summary>
    public IList<MetadataSqlAppendFieldValue> Values { get; set; } = new List<MetadataSqlAppendFieldValue>();

    /// <summary>
    ///     当前字段是否不添加<see cref="MetadataCodeMap.Label" />前缀且不做无标签码号检测。
    /// </summary>
    public bool IsFixed { get; set; }

    /// <summary>
    ///     当类型是<see cref="MetadataSqlFieldValueType.Categorical" />时，此属性是分类列表的定义，
    ///     其中，Key是码号，Value是描述。
    /// </summary>
    public IDictionary<string, string> CodeMapping { get; set; } = new Dictionary<string, string>();

    /// <summary>
    ///     SQL字段名，需要是完全限定名称，不能包含类似 [..] 的迭代语法。
    /// </summary>
    public string Name { get; set; } = string.Empty;
}


/// <summary>
///     配置SQL额外字段的赋值信息。
/// </summary>
[Serializable]
public class MetadataSqlAppendFieldValue
{
    /// <summary>
    ///     赋值当前值的筛选器表达式。
    /// </summary>
    public string Expression { get; set; } = string.Empty;

    /// <summary>
    ///     如果设置了此属性值，只有指定名称的文件内容才会进行赋值判断。
    /// </summary>
    public IList<string> FileNames { get; set; } = new List<string>();


    /// <summary>
    ///     需要添加的值。
    /// </summary>
    public string Value { get; set; } = string.Empty;


    /// <summary>
    ///     解析后的表达式结果。
    /// </summary>
    public Expression? ParsedExpression { get; set; }


    /// <summary>
    ///     当前配置的文件名列表中是否包含给定的文件名。
    /// </summary>
    /// <param name="file">给定文件名，不区分大小写</param>
    /// <returns></returns>
    public bool ContainsFile(string file)
    {
        return FileNames.Any(e =>
            Path.GetFullPath(e).Equals(Path.GetFullPath(file), StringComparison.OrdinalIgnoreCase));
    }
}